/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CORE_INC_CARD_CHANNEL_H
#define CORE_INC_CARD_CHANNEL_H

#include "apdu_core_defines.h"
#include "command_apdu.h"
#include "response_apdu.h"
#include "se_base_services_defines.h"

#ifdef __cplusplus
extern "C" {
#endif

// interface defines
typedef struct SecureElementContext SecureElementContext;

typedef ResultCode ChannelTransmit(SecureElementContext *context, const uint8_t *command, uint32_t commandLen,
    uint8_t *response, uint32_t *responseLen);

typedef ResultCode ChannelOpen(SecureElementContext *context);

typedef ResultCode ChannelGetOpenResponse(SecureElementContext *context, uint8_t *response, uint32_t *responseLen);

typedef ResultCode ChannelClose(SecureElementContext *context);

typedef ResultCode ChannelSecureOpen(SecureElementContext *context, const uint8_t *key, uint32_t keyLen,
    uint8_t keyVersion, uint8_t keyId);

typedef ResultCode ChannelSecureClose(SecureElementContext *context);

typedef ResultCode ResponseChecker(const ResponseApdu *apdu);

typedef struct CardChannel CardChannel;

typedef struct ChannelOperations {
    ChannelOpen *open;
    ChannelSecureOpen *openSecure;
    ChannelClose *close;
    ChannelSecureClose *closeSecure;
    ChannelTransmit *transmit;
    ChannelGetOpenResponse *getOpenResponse;
} ChannelOperations;

typedef ResultCode ScpEnableChecker(const CardChannel *channel);

#define SECURE_OPTION_KEY_MAX_SIZE 64
typedef struct SecureOption {
    uint8_t key[SECURE_OPTION_KEY_MAX_SIZE];
    uint32_t keyLen;
    uint8_t keyVersion;
    uint8_t keyId;
    uint32_t enable;
    ScpEnableChecker *checker;
} SecureOption;

typedef struct CardChannel {
    SecureElementContext *context;
    SecureOption secureOption;
    ChannelOperations oper;
} CardChannel;

// construct func
CardChannel *ConstructCardChannel(SecureElementContext *context, ChannelOperations *oper);

// destruct func
void DestructCardChannel(CardChannel *channel);

// public methods
ResultCode ChannelOpenChannel(const CardChannel *channel);

ResultCode ChannelCloseChannel(const CardChannel *channel);

ResultCode ChannelOpenChannelSecure(const CardChannel *channel, const uint8_t *key, uint32_t keyLen, uint8_t keyVersion,
    uint8_t keyId);

ResultCode ChannelCloseChannelSecure(const CardChannel *channel);

ResultCode ChannelEnableSecureChannelProtocol(CardChannel *channel, const uint8_t *key, uint32_t keyLen,
    uint8_t keyVersion, uint8_t keyId);

ResultCode ChannelSetSecureChannelProtocolChecker(CardChannel *channel, ScpEnableChecker checker);

ResultCode ChannelTransmitApdu(const CardChannel *channel, CommandApdu *commandApdu, ResponseApdu **responseApdu);

ResultCode ChannelGetOpenChannelResponse(const CardChannel *channel, uint8_t *response, uint32_t *responseLen);

ResultCode DefaultResponseChecker(const ResponseApdu *apdu);

ResultCode DefaultScpEnableChecker(const CardChannel *channel);

ResultCode ChannelOpenTransmitCloseWithRetry(const CardChannel *channel, uint32_t retry, ResponseChecker checker,
    CommandApdu *commandApdu, ResponseApdu **responseApdu);

#define ChanneEnableSecureChannelProtocol ChannelEnableSecureChannelProtocol

#ifdef __cplusplus
}
#endif

#endif // CORE_INC_CARD_CHANNEL_H